home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Peter Lewis / Finger 1.3.5 / source / Finger / Fingers.p < prev    next >
Encoding:
Text File  |  1992-02-24  |  19.8 KB  |  833 lines  |  [TEXT/PJMM]

  1. unit Fingers;
  2.  
  3. { This code is part of the Finger/Fingerd source code, written in THINK Pascal 4 }
  4. { Copyright 1991-1992 Peter N Lewis }
  5. { If you use this code, you must give me credit in your about box and documentation }
  6.  
  7. interface
  8.  
  9.     uses
  10.         OOMainLoop;
  11.  
  12.     const
  13.         WT_FingerOutput = 'FOut';
  14.  
  15.     type
  16.         DefObject = object(DObject)
  17.                 procedure CalculateRegion (var rgn: rgnHandle);
  18.                 override;
  19.                 function DoMainClick (er: eventRecord): boolean;
  20.                 override;
  21.             end;
  22.  
  23.     var
  24.         giveOoMerror: boolean;   { Enable out of mem error every time a menu is chosen }
  25.         has_MacTCP11: boolean;
  26.  
  27.     procedure InitFingers;
  28.     procedure FinishFingers;
  29.     procedure HandleFingerTCPEvents;
  30.     procedure Finger;
  31.     procedure DoFingerCommand (s: str255);
  32.     procedure FailAlert (s: str255; n: longInt);
  33.     function IsFingerWindow (wp: windowPtr): boolean;
  34.     function GetFingerTE (wp: windowPtr): TEHandle;
  35.  
  36. implementation
  37.  
  38.     uses
  39.         MyUtilities, MyFileSystem, AppGlobals, Preferences, MyTranslate82728, {}
  40.         TCPTypes, TCPStuff, TCPConnections, OOStaticEdit, {}
  41.         FingerDaemon, MyInternetMenu, MyAddressInput, MyGrowZones;
  42.  
  43.     const
  44.         my_waiting_cursor = 128;
  45.  
  46.     type
  47.         FIObject = object(AIObject)
  48.                 procedure Create (id: integer);
  49.                 override;
  50.                 procedure DoItem (item: integer);
  51.                 override;
  52.                 procedure DoKey (modifiers: integer; ch: char; code: integer);
  53.                 override;
  54.                 procedure PackStringBlank (var s: str255);
  55.                 override;
  56.                 procedure PackString (var s: str255);
  57.                 override;
  58.                 procedure UnPackString (s: str255);
  59.                 override;
  60.                 function IsOKOn: boolean;
  61.                 override;
  62.                 function IsSetDefaultOn: boolean;
  63.                 override;
  64.                 procedure DoCommand (s: str255);
  65.                 override;
  66.                 procedure GetDialog;
  67.                 override;
  68.             end;
  69.         FOObject = object(DObject)
  70.                 textob: TEStaticObject;
  71.                 connection: ConnectionIndex;
  72.                 datahandle: handle;
  73.                 procedure Create (id: integer);
  74.                 override;
  75.                 procedure Destroy;
  76.                 override;
  77.                 procedure Resize;
  78.                 override;
  79.                 function EditMenuEnabled: boolean;
  80.                 override;
  81.                 procedure SetEditMenuItem (item: integer);
  82.                 override;
  83.                 procedure DoEditMenu (item: integer);
  84.                 override;
  85.                 procedure Zoom (code: integer);
  86.                 override;
  87.                 function DoMainClick (er: eventRecord): boolean;
  88.                 override;
  89.                 procedure DoItemWhere (er: eventRecord; item: integer);
  90.                 override;
  91.                 procedure DoActivateDeactivate (activate: boolean);
  92.                 override;
  93.                 procedure CalculateRegion (var rgn: rgnHandle);
  94.                 override;
  95.             end;
  96.  
  97.     const
  98.         finger_input_refcon = -1;
  99.         fi_port = 7;
  100.         fo_text_item = 1;
  101.         ports_strh_id = 300;
  102.         finger_str_index = 1;
  103.         finger_port_index = 2;
  104.         whois_str_index = 3;
  105.         whois_port_index = 4;
  106.         general_strh_id = 400;
  107.         cmd_key_index = 2;
  108.         finger_button_index = 3;
  109.         whois_button_index = 4;
  110.         daemons_max = 10;
  111.  
  112.     var
  113.         max_daemons: integer;
  114.         fingerd: array[1..daemons_max] of connectionIndex;
  115.         fingerdata: array[1..daemons_max] of handle;
  116.         default_whois: boolean;
  117.         fingering: integer;
  118.         trans: transTable;
  119.         finger_port, whois_port, fingerd_port: integer;
  120.         whois_str: str63;
  121.         max_sane_handle_size: longInt;
  122.         cmd_key: char;
  123.         finger_button_str, whois_button_str: string[10];
  124.  
  125.     procedure FailAlert (s: str255; n: longInt);
  126.         var
  127.             s2: str255;
  128.             a: integer;
  129.     begin
  130.         if n = 0 then
  131.             s2 := ''
  132.         else
  133.             NumToString(n, s2);
  134.         Paramtext(s, s2, '', '');
  135.         a := Alert(fail_alert_id, nil);
  136.     end;
  137.  
  138.     procedure PackName (var s: str255; name, mach: str255; whois: boolean);
  139.         function hasat (n: str255): boolean;
  140.             var
  141.                 i: integer;
  142.         begin
  143.             hasat := Pos('@', n) > 0;
  144.         end;
  145.  
  146.         procedure Validate (n: str255);
  147.             var
  148.                 i: integer;
  149.         begin
  150.             s := n;
  151.             if s[length(s)] = '@' then
  152.                 s := '?';
  153.             i := 1;
  154.             while i < length(s) do begin
  155.                 if (s[i] = '@') and (s[i + 1] = '@') then
  156.                     s := '?';
  157.                 i := i + 1;
  158.             end;
  159.             if Pos(concat(':', whois_str), s) <> 0 then
  160.                 s := '?';
  161.         end;
  162.     begin
  163.         s := '?';
  164.         if hasat(name) then begin
  165.             if mach = '' then
  166.                 Validate(name);
  167.         end
  168.         else if hasat(mach) then begin
  169.             if name = '' then
  170.                 Validate(mach);
  171.         end
  172.         else begin
  173.             Validate(concat(name, '@', mach));
  174.         end;
  175.         if (s <> '?') and whois then
  176.             s := concat(s, ':', whois_str);
  177.     end;
  178.  
  179.     procedure UnpackName (s: str255; var name, mach: str255; var whois: boolean);
  180.         var
  181.             p: integer;
  182.     begin
  183.         p := length(s);
  184.         while s[p] <> '@' do
  185.             p := p - 1;
  186.         name := copy(s, 1, p - 1);
  187.         mach := copy(s, p + 1, 255);
  188.         p := Pos(concat(':', whois_str), mach);
  189.         whois := p > 0;
  190.         if whois then
  191.             mach := copy(mach, 1, p - 1);
  192.     end;
  193.  
  194.     function IsFingerWindow (wp: windowPtr): boolean;
  195.     begin
  196.         IsFingerWindow := GetWType(wp) = WT_FingerOutput;
  197.     end;
  198.  
  199.     function GetFingerTE (wp: windowPtr): TEHandle;
  200.     begin
  201.         GetFingerTE := FOObject(GetWObject(wp)).textob.te;
  202.     end;
  203.  
  204.     procedure FIObject.PackStringBlank (var s: str255);
  205.     begin
  206.         if (default_machine = '') and (default_user = '') then
  207.             if default_whois then
  208.                 s := concat('@:', whois_str) {sleeze}
  209.             else
  210.                 s := '@'
  211.         else
  212.             PackName(s, default_user, default_machine, default_whois);
  213.     end;
  214.  
  215.     procedure FIObject.PackString (var s: str255);
  216.     begin
  217.         PackName(s, default_user, default_machine, default_whois);
  218.     end;
  219.  
  220.     procedure FIObject.UnPackString (s: str255);
  221.     begin
  222.         UnPackName(s, default_user, default_machine, default_whois);
  223.     end;
  224.  
  225.     function FIObject.IsOKOn: boolean;
  226.         var
  227.             s, s1, s2: str255;
  228.     begin
  229.         GetItemText(window, ai_user, s1);
  230.         GetItemText(window, ai_machine, s2);
  231.         PackName(s, s1, s2, false);
  232.         IsOkOn := s <> '?';
  233.     end;
  234.  
  235.     function FIObject.IsSetDefaultOn: boolean;
  236.         var
  237.             s, s1, s2: str255;
  238.     begin
  239.         GetItemText(window, ai_user, s1);
  240.         GetItemText(window, ai_machine, s2);
  241.         PackName(s, s1, s2, false);
  242.         IsSetDefaultOn := (s <> '?') or ((s1 = '') and (s2 = ''));
  243.     end;
  244.  
  245.     procedure FIObject.GetDialog;
  246.         var
  247.             kind: integer;
  248.             h: handle;
  249.             r: rect;
  250.     begin
  251.         inherited GetDialog;
  252.         GetDItem(window, fi_port, kind, h, r);
  253.         default_whois := GetCtlValue(controlhandle(h)) <> 0;
  254.     end;
  255.  
  256.     procedure TogglePort (wp: windowPtr);
  257.         var
  258.             kind: integer;
  259.             h: controlHandle;
  260.             r: rect;
  261.             cv: integer;
  262.     begin
  263.         GetDItem(wp, fi_port, kind, handle(h), r);
  264.         cv := 1 - GetCtlValue(h);
  265.         SetCtlValue(h, cv);
  266.         GetDItem(wp, ai_ok, kind, handle(h), r);
  267.         if cv = 0 then {finger}
  268.             SetCTitle(h, finger_button_str)
  269.         else
  270.             SetCTitle(h, whois_button_str);
  271.     end;
  272.  
  273.     procedure FIObject.Create (id: integer);
  274.         var
  275.             kind: integer;
  276.             h: handle;
  277.             r: rect;
  278.     begin
  279.         inherited Create(id);
  280.         GetDItem(window, fi_port, kind, h, r);
  281.         SetCtlValue(controlhandle(h), ord(default_whois));
  282.         TogglePort(window); { Set up Finger/Whois button }
  283.         TogglePort(window);
  284.         ShowWindow(window);
  285.     end;
  286.  
  287.     procedure DoFingerCommand (s: str255);
  288.         var
  289.             cp: connectionIndex;
  290.             oe: OSErr;
  291.             s1, s2: str255;
  292.             whois: boolean;
  293.             sh: stringHandle;
  294.     begin
  295.         UnpackName(s, s1, s2, whois);
  296.         sh := NewString(s);
  297.         oe := FindAddress(cp, s2, sh);
  298.         if oe <> noErr then begin
  299.             FailAlert('FindAddress failed with error ', oe);
  300.             DisposHandle(handle(sh));
  301.         end
  302.         else
  303.             fingering := fingering + 1;
  304.     end;
  305.  
  306.     procedure FIObject.DoCommand (s: str255);
  307.     begin
  308.         DoFingerCommand(s);
  309.     end;
  310.  
  311.     procedure FIObject.DoItem (item: integer);
  312.     begin
  313.         case item of
  314.             fi_port: 
  315.                 TogglePort(window);
  316.             otherwise
  317.                 inherited DoItem(item);
  318.         end;
  319.     end;
  320.  
  321.     procedure FIObject.DoKey (modifiers: integer; ch: char; code: integer);
  322.     begin
  323.         if (BAND(modifiers, cmdKey) <> 0) and (IUEqualString(ch, cmd_key) = 0) then
  324.             TogglePort(window);
  325.         inherited DoKey(modifiers, ch, code);
  326.     end;
  327.  
  328.     procedure FailOutOfMemory;
  329.     begin
  330.         if giveOoMerror then begin
  331.             FailAlert('I have run out of Memory.  Give me some more!', 0);
  332.             giveOoMerror := false;
  333.         end;
  334.     end;
  335.  
  336.     function ReadChars (tcpc: TCPConnectionPtr; h: handle; count: longInt; striplf: boolean; important: boolean): boolean;
  337. { return true if out of memory }
  338.         var
  339.             size, i, j: longInt;
  340.             b: signedByte;
  341.             p: ptr;
  342.             oe: OSErr;
  343.     begin
  344.         ReadChars := false;
  345.         if not important and MemoryCritical then begin
  346.             FailOutOfMemory;
  347.             oe := TCPFlush(tcpc);
  348.             ReadChars := true;
  349.             Exit(ReadChars);
  350.         end;
  351.         size := GetHandleSize(h);
  352.         if size + count > max_sane_handle_size then
  353.             count := max_sane_handle_size - size;
  354.         if count > 0 then begin
  355.             SetHandleSize(h, size + count);
  356.             if GetHandleSize(h) <> size + count then begin
  357.                 FailOutOfMemory;
  358.                 oe := TCPFlush(tcpc);
  359.                 ReadChars := true;
  360.                 Exit(ReadChars);
  361.             end
  362.             else begin
  363.                 HLock(h);
  364.                 oe := TCPReceiveChars(tcpc, ptr(longInt(h^) + size), count);
  365.                 j := size;
  366.                 if oe = noErr then begin
  367.                     if striplf then begin
  368.                         for i := size to size + count - 1 do begin
  369.                             b := ptr(longInt(h^) + i)^;
  370.                             case b of
  371.                                 10:  begin
  372.                                     p := ptr(longInt(h^) + j);
  373.                                     p^ := trans[13];
  374.                                     j := j + 1;
  375.                                 end;
  376.                                 13: 
  377.                                     ;
  378.                                 otherwise begin
  379.                                     p := ptr(longInt(h^) + j);
  380.                                     p^ := trans[BAND(b, $FF)];
  381.                                     j := j + 1;
  382.                                 end;
  383.                             end;
  384.                         end;
  385.                     end
  386.                     else
  387.                         j := size + count;
  388.                 end;
  389.                 HUnlock(h);
  390.                 if j <> size + count then
  391.                     SetHandleSize(h, j);
  392.             end;
  393.         end
  394.         else
  395.             oe := TCPFlush(tcpc);
  396.     end;
  397.  
  398.     function StripCRLF (h: handle): boolean;
  399.         var
  400.             size, i: longInt;
  401.             b: signedByte;
  402.     begin
  403.         StripCRLF := false;
  404.         size := GetHandleSize(h);
  405.         for i := 0 to size - 1 do begin
  406.             b := ptr(longInt(h^) + i)^;
  407.             if (b = 13) or (b = 10) then begin
  408.                 StripCRLF := true;
  409.                 SetHandleSize(h, i);
  410.                 leave;
  411.             end;
  412.         end;
  413.     end;
  414.  
  415. {$ Init}
  416.     procedure InitFingers;
  417.         var
  418.             th: handle;
  419.             i: integer;
  420.             s: str255;
  421.             temp: longInt;
  422.         procedure GetIndNumber (id, index: integer; var num: integer);
  423.             var
  424.                 temp: longInt;
  425.         begin
  426.             GetIndString(s, id, index);
  427.             StringToNum(s, temp);
  428. {$PUSH}
  429. {$R-}
  430.             num := temp;
  431. {$R-}
  432.         end;
  433.     begin
  434.         if has_MacTCP11 then begin
  435.             GetIndNumber(fingerd_strh, daemons_max_index, max_daemons);
  436.             if max_daemons > daemons_max then
  437.                 max_daemons := daemons_max;
  438.         end
  439.         else
  440.             max_daemons := 1;
  441.         for i := 1 to max_daemons do
  442.             fingerd[i] := no_connection;
  443.         fingering := 0;
  444.         GetTrans(translateInResID, trans);
  445.         GetIndNumber(fingerd_strh, fingerd_port_index, fingerd_port);
  446.         GetIndNumber(ports_strh_id, finger_port_index, finger_port);
  447.         GetIndNumber(ports_strh_id, whois_port_index, whois_port);
  448.         GetIndString(s, ports_strh_id, whois_str_index);
  449.         whois_str := s;
  450.         GetIndString(s, fingerd_strh, maxplansize_index);
  451.         StringToNum(s, max_sane_handle_size);
  452.         GetIndString(s, general_strh_id, cmd_key_index);
  453.         cmd_key := s[1];
  454.         GetIndString(s, general_strh_id, finger_button_index);
  455.         finger_button_str := s;
  456.         GetIndString(s, general_strh_id, whois_button_index);
  457.         whois_button_str := s;
  458.         InitDaemon;
  459.         InitAddressInput;
  460.     end;
  461.  
  462. {$ Term}
  463.     procedure FinishFingers;
  464.     begin
  465.         FinishDaemon;
  466.     end;
  467.  
  468.     procedure FOObject.Resize;
  469.         var
  470.             kind, fsize, bt, rt: integer;
  471.             h: handle;
  472.             r: rect;
  473.             finfo: FontInfo;
  474.     begin
  475.         SetPort(window);
  476.         GetDItem(window, fo_text_item, kind, h, r);
  477.         r := windowPeek(window)^.port.portRect;
  478.         InsetRect(r, -1, -1);
  479.         SetDItem(window, fo_text_item, kind, h, r);
  480.         textob.Resize;
  481.     end;
  482.  
  483.     procedure FOObject.Zoom (code: integer);
  484.         var
  485.             lines: integer;
  486.     begin
  487.         if code = inZoomOut then begin
  488.             with textob.te^^ do begin
  489.                 lines := nLines;
  490.         {since nLines isn’t right if the last character is a return, check for that case}
  491.                 if Ptr(ORD(hText^) + teLength - 1)^ = 13 then
  492.                     lines := lines + 1;
  493.                 zoomSize.v := lines * lineHeight + 20;
  494.             end;
  495.             if zoomSize.v < growRect.top then
  496.                 zoomSize.v := growRect.top;
  497.             if zoomSize.v > growRect.bottom then
  498.                 zoomSize.v := growRect.bottom;
  499.         end;
  500.         inherited Zoom(code);
  501.     end;
  502.  
  503.     procedure FOObject.DoActivateDeactivate (activate: boolean);
  504.     begin
  505.         textob.DoActivateDeactivate(activate);
  506.     end;
  507.  
  508.     procedure Finger;
  509.         var
  510.             fio: FIObject;
  511.     begin
  512.         new(fio);
  513.         fio.Create(finger_input_dialog_id);
  514.         ShowWindow(fio.window);
  515.     end;
  516.  
  517.     function FOObject.EditMenuEnabled: boolean;
  518.     begin
  519.         EditMenuEnabled := textob.EditMenuEnabled;
  520.     end;
  521.  
  522.     procedure FOObject.SetEditMenuItem (item: integer);
  523.     begin
  524.         textob.SetEditMenuItem(item);
  525.     end;
  526.  
  527.     procedure FOObject.DoEditMenu (item: integer);
  528.     begin
  529.         textob.DoEditMenu(item);
  530.     end;
  531.  
  532.     function FOObject.DoMainClick (er: eventRecord): boolean;
  533.         var
  534.             pt: point;
  535.     begin
  536.         pt := er.where;
  537.         SetPort(window);
  538.         GlobalToLocal(pt);
  539.         if not PtInRect(pt, textob.te^^.viewRect) then
  540.             SetCursor(arrow);
  541.         DoMainClick := inherited DoMainClick(er);
  542.     end;
  543.  
  544.     procedure FOObject.DoItemWhere (er: eventRecord; item: integer);
  545.     begin
  546.         textob.DoItemWhere(er, item);
  547.         if textob.te^^.selStart = textob.te^^.selEnd then begin  { kludge to make the carret go away }
  548.             TEDeactivate(textob.te);
  549.             TEActivate(textob.te);
  550.         end;
  551.     end;
  552.  
  553.     function DefObject.DoMainClick (er: eventRecord): boolean;
  554.     begin
  555.         SetCursor(arrow);
  556.         DoMainClick := inherited DoMainClick(er);
  557.     end;
  558.  
  559.     procedure DefObject.CalculateRegion (var rgn: rgnHandle);
  560.     begin
  561.         if fingering > 0 then
  562.             SetCursor(GetCursor(my_waiting_cursor)^^)
  563.         else
  564.             SetCursor(arrow);
  565.         rgn := nil;
  566.     end;
  567.  
  568.     procedure FOObject.CalculateRegion (var rgn: rgnHandle);
  569.         var
  570.             pt: point;
  571.             rgn2: rgnHandle;
  572.             r: rect;
  573.     begin
  574.         rgn := NewRgn;
  575.  
  576.         r := textob.te^^.viewRect;
  577.         SetPort(window);
  578.         GetMouse(pt);
  579.         RectRgn(rgn, r);
  580.         if PtInRect(pt, r) then begin
  581.             SetCursor(GetCursor(iBeamCursor)^^);
  582.         end
  583.         else begin
  584.             if fingering > 0 then
  585.                 SetCursor(GetCursor(my_waiting_cursor)^^)
  586.             else
  587.                 SetCursor(arrow);
  588.             rgn2 := NewRgn;
  589.             SetRectRgn(rgn2, -30000, -30000, 30000, 30000);
  590.             DiffRgn(rgn2, rgn, rgn);
  591.             DisposeRgn(rgn2);
  592.         end;
  593.     end;
  594.  
  595.     procedure DrawFingerText (dp: dialogPtr; item: integer);
  596.     begin
  597.         FOObject(GetWObject(dp)).textob.Draw;
  598.     end;
  599.  
  600.     procedure InsertText (sto: TEStaticObject; h: handle);
  601.         var
  602.             s, t: longInt;
  603.     begin
  604.         s := GetHandleSize(h);
  605.         t := GetHandleSize(sto.te^^.hText);
  606.         SetHandleSize(sto.te^^.hText, t + s);
  607.         if GetHandleSize(sto.te^^.hText) <> t + s then begin
  608.             FailOutOfMemory;
  609.         end
  610.         else begin
  611.             BlockMove(h^, ptr(longInt(sto.te^^.hText^) + t), s);
  612.             TECalText(sto.te);
  613.             sto.Adjust;
  614.         end;
  615.     end;
  616.  
  617.     procedure FOObject.Create (id: integer);
  618.         var
  619.             kind, lw: integer;
  620.             h: handle;
  621.             r: rect;
  622.             temptextob: TEStaticObject;
  623.     begin
  624.         inherited Create(id);
  625.         window_type := WT_FingerOutput;
  626.         h := NewHandle(0);
  627.         datahandle := h;
  628.         SetPort(window);
  629.         TextFont(monaco);
  630.         TextSize(9);
  631.         new(temptextob);
  632.         textob := temptextob;
  633.         lw := CharWidth('a') * 80;
  634.         textob.Create(window, fo_text_item, lw, true, true, true, true);
  635.         zoomSize.h := lw + 20;
  636.         GetDItem(window, fo_text_item, kind, h, r);
  637.         SetDItem(window, fo_text_item, kind, handle(@DrawFingerText), r);
  638.         Resize;
  639.     end;
  640.  
  641.     procedure FOObject.Destroy;
  642.     begin
  643.         if connection <> no_connection then begin
  644.             AbortConnection(connection);
  645.             SetDataPtr(connection, POINTER(-1));
  646.         end;
  647.         if datahandle <> nil then
  648.             DisposHandle(datahandle);
  649.         datahandle := nil;
  650.         textob.Destroy;
  651.         inherited Destroy;
  652.     end;
  653.  
  654.     function FindPort (whois: boolean): integer;
  655.     begin
  656.         if whois then
  657.             FindPort := whois_port
  658.         else
  659.             FindPort := finger_port;
  660.     end;
  661.  
  662.     procedure AddIP (sh: stringHandle; ip: longInt);
  663.         var
  664.             s1, s2, sip: str255;
  665.             whois: boolean;
  666.     begin
  667.         if prefs.showIP then begin
  668.             UnpackName(sh^^, s1, s2, whois);
  669.             FindString(ip, sip);
  670.             if sip <> s2 then begin
  671.                 s2 := concat(s2, ' (', sip, ')');
  672.                 PackName(sip, s1, s2, whois);
  673.                 SetHandleSize(handle(sh), Length(sip) + 1);
  674.                 if MemError = noErr then
  675.                     BlockMove(@sip, handle(sh)^, Length(sip) + 1);
  676.             end;
  677.         end;
  678.     end;
  679.  
  680.     procedure HandleFingerTCPEvents;
  681.         var
  682.             oe: OSErr;
  683.             cer: connectionEventRecord;
  684.             s, s1, s2: str255;
  685.             dlg: dialogPtr;
  686.             cp: connectionIndex;
  687.             foo: FOObject;
  688.             texth: handle;
  689.             remoteIP: longInt;
  690.             defrefnum, i, ps: integer;
  691.             whois: boolean;
  692.             prefs_fs: FSSpec;
  693.             prefs_rn: integer;
  694.     begin
  695.         for i := 1 to max_daemons do begin
  696.             if prefs.plan_enabled and (fingerd[i] = no_connection) then begin
  697.                 oe := NewPassiveConnection(fingerd[i], fingerd_port, 0, 0, nil);
  698.                 if oe <> noErr then begin
  699.                     FailAlert('The Finger Daemon failed to open', oe);
  700.                     prefs.plan_enabled := false;
  701.                     fingerd[i] := no_connection;
  702.                 end;
  703.             end
  704.             else if not prefs.plan_enabled and (fingerd[i] <> no_connection) then begin
  705.                 CloseConnection(fingerd[i]);
  706.             end;
  707.         end;
  708.         while GetConnectionEvent(any_connection, cer) do
  709.             with cer do begin
  710.                 case event of
  711.                     C_Found:  begin
  712.                         UnpackName(stringHandle(dataptr)^^, s1, s2, whois);
  713.                         AddIP(stringHandle(dataptr), value);
  714.                         oe := NewActiveConnection(cp, value, FindPort(whois), dataptr);
  715.                         if oe <> noErr then begin
  716.                             FailAlert(concat('Failed to open a connection to "', s2, '"'), oe);
  717.                             DisposHandle(handle(dataptr));
  718.                         end;
  719.                     end;
  720.                     C_SearchFailed:  begin
  721.                         UnpackName(stringHandle(dataptr)^^, s1, s2, whois);
  722.                         FailAlert(concat('The machine "', s2, '" doesn''t seem to exist'), 0);
  723.                         DisposHandle(handle(dataptr));
  724.                         fingering := fingering - 1;
  725.                     end;
  726.                     C_FailedToOpen:  begin
  727.                         UnpackName(stringHandle(dataptr)^^, s1, s2, whois);
  728.                         if timedout then
  729.                             FailAlert(concat('The connection timed out looking for machine "', s2, '"'), 0)
  730.                         else
  731.                             FailAlert(concat('Machine "', s2, '" doesn''t answer'), 0);
  732.                         DisposHandle(handle(dataptr));
  733.                         SetDataPtr(connection, POINTER(-1));
  734.                         fingering := fingering - 1;
  735.                     end;
  736.                     C_Established:  begin
  737.                         if dataptr = nil then begin
  738.                             for i := 1 to max_daemons do
  739.                                 if fingerd[i] = connection then
  740.                                     fingerdata[i] := NewHandle(0);
  741.                         end
  742.                         else begin
  743.                             if MemoryCritical then begin
  744.                                 FailOutOfMemory;
  745.                                 DisposHandle(handle(dataptr));
  746.                                 SetDataPtr(connection, -1);
  747.                                 CloseConnection(connection);
  748.                                 fingering := fingering - 1;
  749.                             end
  750.                             else begin
  751.                                 s := stringHandle(dataptr)^^;
  752.                                 DisposHandle(handle(dataptr));
  753.                                 UnpackName(s, s1, s2, whois);
  754.                                 s1 := concat(s1, chr(13), chr(10));
  755.                                 oe := TCPSend(tcpc, @s1[1], length(s1));
  756.                                 new(foo);
  757.                                 foo.Create(finger_output_dialog_id);
  758.                                 SetWTitle(foo.window, s);
  759.                                 SetDataPtr(connection, foo);
  760.                                 foo.connection := connection;
  761.                                 if prefs.showIP then begin
  762.                                     UnpackName(s, s1, s2, whois);
  763.                                     ps := Pos(' (', s2);
  764.                                     if ps > 0 then begin
  765.                                         s2 := copy(s2, 1, ps - 1);
  766.                                         PackName(s, s1, s2, whois);
  767.                                         UnpackName(s, s1, s2, whois);
  768.                                     end;
  769.                                 end;
  770.                                 AddInternetCommand(s);
  771.                             end;
  772.                         end;
  773.                     end;
  774.                     C_CharsAvailable:  begin
  775.                         if dataptr = nil then begin
  776.                             i := 1;
  777.                             while (i < max_daemons) and (fingerd[i] <> connection) do
  778.                                 i := i + 1;
  779.                             if ReadChars(tcpc, fingerdata[i], value, false, true) then begin { panic! }
  780.                                 CloseConnection(connection);
  781.                             end
  782.                             else if StripCRLF(fingerdata[i]) then begin
  783. {$PUSH}
  784. {$R-}
  785.                                 s[0] := chr(GetHandleSize(fingerdata[i]));
  786.                                 BlockMove(fingerdata[i]^, @s[1], ord(s[0]));
  787. {$POP}
  788.                                 GetPrefsFSSpec(prefs_fs);
  789.                                 prefs_rn := OpenPrefsFile(prefs_fs);
  790.                                 SendPlan(tcpc, prefs.plan_vrn, prefs.plan_dirID, prefs.plan_name, s);
  791.                                 if prefs_rn <> -1 then
  792.                                     CloseResFile(prefs_rn);
  793.                                 CloseConnection(connection);
  794.                             end;
  795.                         end
  796.                         else if dataptr <> POINTER(-1) then begin
  797.                             if MemoryCritical then begin
  798.                                 FOObject(dataptr).Destroy;
  799.                                 FailOutOfMemory;
  800.                                 fingering := fingering - 1;
  801.                             end
  802.                             else if ReadChars(tcpc, FOObject(dataptr).datahandle, value, true, false) then begin
  803.                                 CloseConnection(connection);
  804.                             end;
  805.                         end;
  806.                     end;
  807.                     C_Closing:  begin
  808.                         CloseConnection(connection);
  809.                     end;
  810.                     C_Closed:  begin
  811.                         if dataptr = nil then begin
  812.                             for i := 1 to max_daemons do
  813.                                 if fingerd[i] = connection then
  814.                                     fingerd[i] := no_connection;
  815.                         end
  816.                         else if dataptr <> POINTER(-1) then begin
  817.                             foo := FOObject(dataptr);
  818.                             InsertText(foo.textob, foo.datahandle);
  819.                             DisposHandle(foo.datahandle);
  820.                             foo.datahandle := nil;
  821.                             foo.connection := no_connection;
  822.                             fingering := fingering - 1;
  823.                             foo.Zoom(inZoomOut);
  824.                             ShowWindow(foo.window);
  825.                         end;
  826.                     end;
  827.                     otherwise
  828.                         ;
  829.                 end;{case}
  830.             end;{while with}
  831.     end;
  832.  
  833. end.